/*
 * ByteSizeFormatter.java
 *
 * Created on 22 May 2007, 21:22
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.cardcopier.file;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;

/**
 *
 * @author Mark
 */
public class ByteSizeFormatter {
    
    public enum Scale { 
        B  { Scale nextScale() { return KB; }},
        KB { Scale nextScale() { return MB; }},
        MB { Scale nextScale() { return GB; }},
        GB { Scale nextScale() { return TB; }},
        TB { Scale nextScale() { return null; }};
        abstract Scale nextScale();
    };
    
    private static final BigDecimal SCALE_DIVIDER = new BigDecimal(1024);
    
    private final Scale maximumScale;
    private final int maxDecimalPlaces;
    private final NumberFormat formatter = new DecimalFormat("#,##0.####");

    public ByteSizeFormatter() {
        this.maximumScale = Scale.TB;
        this.maxDecimalPlaces = 2;
    }

    public ByteSizeFormatter(Scale maximumScale, int maxDecimalPlaces) {
        this.maximumScale = maximumScale;
        this.maxDecimalPlaces = maxDecimalPlaces;
    }
    
    public String format(long sizeInBytes) {
        Scale scale = Scale.B;
        Scale nextScale = getNextScale(scale);        
        BigDecimal size = new BigDecimal(sizeInBytes);
        
        while (size.compareTo(SCALE_DIVIDER) > 0 && nextScale != null) {
            size = size.divide(SCALE_DIVIDER);
            scale = nextScale;
            nextScale = getNextScale(scale);
        }

        size = size.setScale(maxDecimalPlaces, RoundingMode.HALF_UP);
        return formatter.format(size) + " " + scale;        
    }
    
    private Scale getNextScale(Scale currentScale) {
        Scale nextScale = null;
        if (!currentScale.equals(maximumScale)) {
            nextScale = currentScale.nextScale();
        }
        return nextScale;
    }
}
